package pres.moling.common.tool;

import java.text.DateFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.util.Date;

import static java.time.temporal.ChronoUnit.*;

/**
 * 日期相关
 *
 * @author moling
 */
public interface DateHelper {


    /**
     * 当前日期输出为字符串
     */
    static String dateFormat() {
        return dateFormat(new Date());   // Formats this date using the specified formatter.
    }


    /**
     * 将指定日期转换为字符串
     */
    static String dateFormat(Date date) {
        return dateFormat(date);// Returns a formatted string using the specified format string and arguments.
    }


//    static String timeFormat(Date date) {
//        return timeFormat(coverLocalDateTime(date));
//    }


    /**
     *  Date date=new Date();
     * 		    //c的使用
     * 		    System.out.printf("全部日期和时间信息：%tc%n",date);
     * 		    //f的使用
     * 		    System.out.printf("年-月-日格式：%tF%n",date);
     * 		    //d的使用
     * 		    System.out.printf("月/日/年格式：%tD%n",date);
     * 		    //r的使用
     * 		    System.out.printf("HH:MM:SS PM格式（12时制）：%tr%n",date);
     * 		    //t的使用
     * 		    System.out.printf("HH:MM:SS格式（24时制）：%tT%n",date);
     * 		    //R的使用
     * 		    System.out.printf("HH:MM格式（24时制）：%tR",date);
     */
    /**
     *  Date date=new Date();
     * 		    //b的使用，月份简称
     * 		    String str=String.format(Locale.US,"英文月份简称：%tb",date);
     * 		    System.out.println(str);
     * 		    System.out.printf("本地月份简称：%tb%n",date);
     * 		    //B的使用，月份全称
     * 		    str=String.format(Locale.US,"英文月份全称：%tB",date);
     * 		    System.out.println(str);
     * 		    System.out.printf("本地月份全称：%tB%n",date);
     * 		    //a的使用，星期简称
     * 		    str=String.format(Locale.US,"英文星期的简称：%ta",date);
     * 		    System.out.println(str);
     * 		    //A的使用，星期全称
     * 		    System.out.printf("本地星期的简称：%tA%n",date);
     * 		    //C的使用，年前两位
     * 		    System.out.printf("年的前两位数字（不足两位前面补0）：%tC%n",date);
     * 		    //y的使用，年后两位
     * 		    System.out.printf("年的后两位数字（不足两位前面补0）：%ty%n",date);
     * 		    //j的使用，一年的天数
     * 		    System.out.printf("一年中的天数（即年的第几天）：%tj%n",date);
     * 		    //m的使用，月份
     * 		    System.out.printf("两位数字的月份（不足两位前面补0）：%tm%n",date);
     * 		    //d的使用，日（二位，不够补零）
     * 		    System.out.printf("两位数字的日（不足两位前面补0）：%td%n",date);
     * 		    //e的使用，日（一位不补零）
     * 		    System.out.printf("月份的日（前面不补0）：%te",date);
     */
    /**
     * //H的使用 System.out.printf("2位数字24时制的小时（不足2位前面补0）:%tH%n", date); //I的使用
     * System.out.printf("2位数字12时制的小时（不足2位前面补0）:%tI%n", date); //k的使用 System.out.printf("2位数字24时制的小时（前面不补0）:%tk%n",
     * date); //l的使用 System.out.printf("2位数字12时制的小时（前面不补0）:%tl%n", date); //M的使用
     * System.out.printf("2位数字的分钟（不足2位前面补0）:%tM%n", date); //S的使用 System.out.printf("2位数字的秒（不足2位前面补0）:%tS%n", date);
     * //L的使用 System.out.printf("3位数字的毫秒（不足3位前面补0）:%tL%n", date); //N的使用 System.out.printf("9位数字的毫秒数（不足9位前面补0）:%tN%n",
     * date); //p的使用 String str = String.format(Locale.US, "小写字母的上午或下午标记(英)：%tp", date); System.out.println(str);
     * System.out.printf("小写字母的上午或下午标记（中）：%tp%n", date); //z的使用 System.out.printf("相对于GMT的RFC822时区的偏移量:%tz%n", date);
     * //Z的使用 System.out.printf("时区缩写字符串:%tZ%n", date); //s的使用 System.out.printf("1970-1-1 00:00:00 到现在所经过的秒数：%ts%n",
     * date); //Q的使用 System.out.printf("1970-1-1 00:00:00 到现在所经过的毫秒数：%tQ%n", date);
     */


    /**
     * Date转 时间字符串
     */
    private static String format(Date date, DateFormat format) {
        return format.format(date);   // Formats a Date into a date-time string.
    }

    /**
     * 日期字符串转Date
     *
     * @param dateStr 字符串
     * @param format  转换格式
     * @return 结果
     */
    private static Date parse(String dateStr, DateFormat format) throws ParseException {
        return format.parse(dateStr);   // Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.
    }

    /**
     * LocalDate 转 Date
     */
    static Date coverDate(LocalDate date) {

        return Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());   // Converts this date-time to an } .
    }

    /**
     * Date 转 LocalDate
     */
    static LocalDate coverLocalDate(Date date) {

        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();   // Gets the } part of this date-time.
    }

    static boolean betweenIn(Date date1, Date date3) {

        LocalDate localDate = LocalDate.now();
        return !coverLocalDate(date1).isAfter(localDate) && !localDate.isBefore(coverLocalDate(date3));

    }


    /**
     * 计算毫秒值与当前时间的差值
     */
    static long diff(long startTime) {
        long end = System.currentTimeMillis();   // Returns the current time in milliseconds.  Note that while the unit of time of the return value is a millisecond,
        if (startTime == 0 || startTime > end) {
            throw new RuntimeException("开始时间不能为0或大于当前时间");   // Constructs a new runtime exception with the specified detail message. The cause is not initialized, and may subsequently be initialized by a
        }
        return end - startTime;
    }

    /**
     * 获取当前时间的毫秒值
     */
    static long currentTimeMillis() {
        return System.currentTimeMillis();   // Returns the current time in milliseconds.  Note that while the unit of time of the return value is a millisecond,
    }

    /**
     * 计算月份差值
     *
     * @param start 起始时间
     * @param end   结束时间
     * @param isUp  是否向上补足
     */
    static long betweenMonth(Temporal start, Temporal end, boolean isUp) {
        return between(start, end, isUp, MONTHS);   // 计算日期差值
    }

    /**
     * 计算日期差值
     *
     * @param start 起始时间
     * @param end   结束时间
     * @param isUp  是否向上补足
     * @param unit  计算时间单位
     */
    static long between(Temporal start, Temporal end, boolean isUp, ChronoUnit unit) {
        if (isUp) {
            long x = unit.between(start, end);   // Calculates the amount of time between two temporal objects.
            long y;
            switch (unit) {
                case YEARS -> {   // Unit that represents the concept of a year. For the ISO calendar system, it is equal to 12 months.
                    y = MONTHS.between(start.plus(x, unit), end);   // Calculates the amount of time between two temporal objects.
                }
                case MONTHS, WEEKS -> {   // Unit that represents the concept of a week. For the ISO calendar system, it is equal to 7 days.
                    y = DAYS.between(start.plus(x, unit), end);   // Calculates the amount of time between two temporal objects.
                }
                case DAYS -> {   // Unit that represents the concept of a day. For the ISO calendar system, it is the standard day from midnight to midnight.
                    y = HOURS.between(start.plus(x, unit), end);   // Calculates the amount of time between two temporal objects.
                }
                default -> {
                    y = 0;
                }
            }
            if (y > 0) {
                return x + 1;
            } else if (y < 0) {
                return x - 1;
            } else {
                return x;
            }

        }
        return unit.between(start, end);   // Calculates the amount of time between two temporal objects.
    }

    /**
     * 计算天差值
     *
     * @param start 起始时间
     * @param end   结束时间
     * @param isUp  是否向上补足
     */
    static long betweenDay(Temporal start, Temporal end, boolean isUp) {
        return between(start, end, isUp, DAYS);   // 计算日期差值
    }

    /**
     * 计算年差值
     *
     * @param start 起始时间
     * @param end   结束时间
     * @param isUp  是否向上补足
     */
    static long betweenYear(Temporal start, Temporal end, boolean isUp) {
        return between(start, end, isUp, YEARS);   // 计算日期差值
    }

}

